/**
 * URL: http://code.google.com/p/nagatsuki-accounting-lib/
 */
/**
 * $Id: JournalServiceImpl.java 116 2009-07-27 08:34:10Z tanaka.akira.2006 $
 */
package com.googlecode.nagatsuki.accountinglib.service.impl;

import java.math.BigDecimal;

import org.apache.commons.lang.StringUtils;

import com.googlecode.nagatsuki.accountinglib.exception.IllegalDateNoException;
import com.googlecode.nagatsuki.accountinglib.exception.UnbalancedException;
import com.googlecode.nagatsuki.accountinglib.model.journal.Entry;
import com.googlecode.nagatsuki.accountinglib.model.journal.Journal;
import com.googlecode.nagatsuki.accountinglib.model.journal.Transaction;
import com.googlecode.nagatsuki.accountinglib.service.JournalService;
import com.googlecode.nagatsuki.accountinglib.service.base.AbstractBaseService;
import com.googlecode.nagatsuki.accountinglib.util.DateNoUtil;

/**
 * 仕訳サービス実装
 *
 * @author tanaka.akira.2006
 *
 */
public class JournalServiceImpl extends AbstractBaseService implements
		JournalService {

	/*
	 * (非 Javadoc)
	 *
	 * @see com.googlecode.nagatsuki.accountinglib.service.JournalService#createTransaction(com.googlecode.nagatsuki.accountinglib.model.journal.Transaction,
	 *      com.googlecode.nagatsuki.accountinglib.model.journal.Entry)
	 */
	@Override
	public void createTransaction(Transaction transaction, Entry entry) {
		if (transaction == null) {
			throw new NullPointerException("transaction is null.");
		}
		if (entry == null) {
			throw new NullPointerException("entry is null.");
		}
		if (StringUtils.isEmpty(transaction.dateNo)) {
			throw new NullPointerException("transaction's dateNo is empty.");
		}

		if (entry.debit == true) {
			transaction.debits.add(entry);
		} else {
			transaction.credits.add(entry);
		}

		return;
	}

	/*
	 * (非 Javadoc)
	 *
	 * @see com.googlecode.nagatsuki.accountinglib.service.JournalService#entry(com.googlecode.nagatsuki.accountinglib.model.journal.Journal,
	 *      java.lang.String,
	 *      com.googlecode.nagatsuki.accountinglib.model.journal.Transaction)
	 */
	@Override
	public void entry(Journal journal, Transaction transaction)
			throws UnbalancedException, IllegalDateNoException {
		if (journal == null) {
			throw new NullPointerException("journal is null.");
		}
		if (transaction == null) {
			throw new NullPointerException("transaction is null.");
		}
		if (StringUtils.isEmpty(transaction.dateNo)) {
			throw new NullPointerException("transaction's dateNo is empty.");
		}

		// 取引番号検証
		DateNoUtil.validate(transaction.dateNo);

		// １取引の貸借バランスチェック
		BigDecimal debitSum = new BigDecimal("0");
		BigDecimal creditSum = new BigDecimal("0");
		for (Entry entry : transaction.debits) {
			debitSum = debitSum.add(entry.amount);
		}
		for (Entry entry : transaction.credits) {
			creditSum = creditSum.add(entry.amount);
		}
		if (!debitSum.equals(creditSum)) {
			throw new UnbalancedException();
		}

		// 記帳
		journal.transactions.put(transaction.dateNo, transaction);
	}

	/*
	 * (非 Javadoc)
	 *
	 * @see com.googlecode.nagatsuki.accountinglib.service.JournalService#delete(com.googlecode.nagatsuki.accountinglib.model.journal.Journal,
	 *      java.lang.String)
	 */
	@Override
	public void delete(Journal journal, String dateNo)
			throws IllegalDateNoException {
		if (journal == null) {
			throw new NullPointerException("journal is null.");
		}
		if (StringUtils.isEmpty(dateNo)) {
			throw new NullPointerException("dateNo is empty.");
		}
		// 取引番号検証
		DateNoUtil.validate(dateNo);
		// 仕訳帳から削除
		journal.transactions.remove(dateNo);

	}

	/*
	 * (非 Javadoc)
	 *
	 * @see com.googlecode.nagatsuki.accountinglib.service.JournalService#update(com.googlecode.nagatsuki.accountinglib.model.journal.Journal,
	 *      java.lang.String,
	 *      com.googlecode.nagatsuki.accountinglib.model.journal.Transaction)
	 */
	@Override
	public void update(Journal journal, String dateNo, Transaction transaction)
			throws IllegalDateNoException {
		if (journal == null) {
			throw new NullPointerException("journal is null.");
		}
		if (transaction == null) {
			throw new NullPointerException("transaction is null.");
		}
		if (StringUtils.isEmpty(dateNo)) {
			throw new NullPointerException("dateNo is empty.");
		}
		// 取引番号検証
		DateNoUtil.validate(dateNo);
		// 仕訳帳を更新
		journal.transactions.put(dateNo, transaction);
	}

}
